package com.wn.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;

import javax.sql.DataSource;
/**
 * 在SpringConfig核心配置类中，加载JdbcConfig配置。
 * JdbcConfig配置类：
 * 1、配置连接池
 * 2、配置事务管理器
 *   因为在SpringConfig中配置了开启事务注解支持，所以这里需要配置一个事务管理器，
 *   作用是用来管理事务；spring已经封装了事务控制的代码，叫做Spring声明式事务。
 *   Spring声明式事务，声明就是定义，表示已经内置事务，直接用。
 */
public class JdbcConfig {

    // @Value 注解作用：可以获取properties配置文件值；前提：需要先加载配置文件
    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /**
     * 创建连接池对象，通过@Bean注解修饰方法，自动把方法返回结果加入ioc容器
     * @return 返回连接池对象，加入容器
     */
    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * 创建事务管理器；这样就可以使用Spring的事务注解：@Transactional，一般在service层控制事务。
     * @return 返回事务管理器且加入ioc容器
     *
     * @Bean注解使用
     * 1、位置：定义在方法上
     * 2、作用：自动把方法返回值加入ioc容器
     * 3、注解参数：@Bean(name="abc") 这里的abc表示加入ioc容器的对象名称
     *      <bean id="abc" class="" />
     * 4、方法参数：
     *    4.1 自动根据方法参数类型，去容器中找该类型对应的对象注入到方法中。
     *    4.2 如果该类型对应的对象有多个，会根据对象名称查找，以参数名作为名称。
     *    4.3 如果参数类型对应的对象有多个，然后根据参数名称去容器中没有找到对象，报错；
     *        解决：
     *          1、@Qualifier("dataSource2")
     *          2、表示只会根据名称dataSource2去容器中查找对象注入方法。
     */
    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}
